#include "RtspServer.h"
#include "RtspCmdLineDeal.h"
#include "ErrorInfo.h"
#include "Log.h"





int StartServer(int *piServerfd,int piPort);
int DealWithClient(int piClientfd);
int SendMsg(int piClientfd,char *psBuf,int piBufLen);
int RecvMsg(int piClientfd, char psBuf[], int piLen);
int SendRtpIpPortInfo(char *pstrIp,int piPort);
int ChangePermission(BOOL pbMarkRoot);
int DeleteCameraInfo(pCameraInfo ppCameraPos);
int GetAllConfigInfo();
int GetConfigValue(char *ppstrFile,char *ppstrSection,char *ppstrItem,char *ppstrValue);
int TrimWrap(char *lstrStr);
int TrimSpace(char *lstrStr);
int OpenMsgQueue(int piKey);
int CloseMsgQueue(int piQueueId);
int SendQueueMsg(int piQueueId,QueueMsgbuf *ppQueueMsgBuf);
int RecvQueueMsg(int piQueueId,QueueMsgbuf *ppQueueMsgBuf);
int StartAllMsgQueue();
int PrintAllCameraInfo();
int PrintOneCameraInfo(CameraInfo *pCameraInfo);
int StartAllRtpServer();
int StartOneRtpServer(CameraInfo *pCameraInfo);


int DoDescribe(int,char*);
int DoOptions(int,char*);
int DoSetup(int, char*);
int DoPlay(int,char*);
int DoPause(int,char*);
int DoTearDown(int,char*);
int DoOrder(int,char*);



RtspCmd gRtspCmdsWithFunc[] = 
{
	{"DESCRIBE", DoDescribe},
	{"OPTIONS", DoOptions},
	{"SETUP", DoSetup},
	{"PLAY", DoPlay},
	{"PAUSE", DoPause},
	{"TEARDOWN", DoTearDown},
	{"ORDER", DoOrder},
	{ NULL, NULL}
};

int giClientCount;
char gstrLocalPath[FILE_MAX_LEN];
char gstrProName[64];
char gstrLogBuf[MAX_LOG_LEN];
static BOOL gbRootPermissionNow=TRUE;
int giServerPort;

SessionGlobalInfo gSessionGlobal;

pCameraInfo gpCameraHead;


int main(int argc,char *argv[])
{
	int liClientfd;
	int liServerfd;
	struct sockaddr_in lsaClientaddr;
	char   *pstr; 
	int liSize=sizeof(struct sockaddr_in);
	int liPid;

 	signal(SIGCLD, SIG_IGN);	/*接收到子进程退出信号处理*/   

	//change the permission to normal, i don't want it has root permission
	ChangePermission(0);
 	
 	strcpy(gstrProName,argv[0]);
 	if(0==memcmp(gstrProName,"./",2))
 		strcpy(gstrProName,gstrProName+2);
 	
 	SetProgrameName(gstrProName);
 	
 	sprintf(gstrLogBuf,"%s programe start ...",gstrProName);
 	WriteLog(LOG_INFO,gstrLogBuf);
 	
 	if(0!=GetAllConfigInfo())
 	{
 		sprintf(gstrLogBuf,"get config file informtion error!");
 		WriteLog(LOG_FAULT,gstrLogBuf);
		return -1;
 	}
 	
 	PrintAllCameraInfo();
 	StartAllRtpServer();

	if(0!=StartAllMsgQueue())
 	{
 		sprintf(gstrLogBuf,"Start all message queue!");
 		WriteLog(LOG_FAULT,gstrLogBuf);
		return -1;
 	}

	if(0!=StartServer(&liServerfd,giServerPort))
	{
		sprintf(gstrLogBuf,"start server error!");
 		WriteLog(LOG_FAULT,gstrLogBuf);
		return -1;
	}
	giClientCount=0;

	sprintf(gstrLogBuf,"wait for client connect ...");
 	WriteLog(LOG_INFO,gstrLogBuf);
	
	/*wait client,fork and deal with cmd*/
	while(1)
	{
		if(-1==(liClientfd=accept(liServerfd,(struct sockaddr *)&lsaClientaddr,&liSize)))
		{
			return ERR_FUNC_ACCEPT;
		}
		
		//在accept执行后 
		memset(&gSessionGlobal,0,sizeof(gSessionGlobal));
		//pstr=(unsigned   char   *)&(lsaClientaddr.sin_addr); 
		//sprintf(gSessionGlobal.strClientAddr,   "%u.%u.%u.%u",pstr[0],pstr[1],pstr[2],pstr[3]); 
		strcpy(gSessionGlobal.strClientAddr,inet_ntoa(lsaClientaddr.sin_addr));

		sprintf(gstrLogBuf,"client connect ip:%s",gSessionGlobal.strClientAddr);
 		WriteLog(LOG_INFO,gstrLogBuf);		

		/*create child*/
		liPid=fork();
		if(0==liPid)
		{
			/*child process ignore server*/
			close(liServerfd);
			/*deal with connect*/
			DealWithClient(liClientfd);
			exit(0);
		}
		else if(liPid>0)
		{
			/*father process ignore client*/
			close(liClientfd);
			giClientCount++;
			continue;
		}
		else
		{
			/*fork error*/
			close(liServerfd);
            continue;
		}
	}
	
	DeleteCameraInfo(gpCameraHead);
	
	return 0;
}

/*start tcp rtsp server*/
int StartServer(int *piServerfd,int piPort)
{
	struct sockaddr_in lsaServeraddr;
	int liSize=sizeof(lsaServeraddr);
	
	sprintf(gstrLogBuf,"tcp server (port:%d) start ...",piPort);
 	WriteLog(LOG_INFO,gstrLogBuf);
	
	/*get current path*/
	memset(gstrLocalPath,0,sizeof(gstrLocalPath));
	getcwd(gstrLocalPath,FILE_MAX_LEN);
	
	/*create tcp stream*/
	if(-1==(*piServerfd=socket(AF_INET,SOCK_STREAM,0)))
	{
		sprintf(gstrLogBuf,"socket error : %s",strerror(errno));
 		WriteLog(LOG_ERROR,gstrLogBuf);
		return ERR_FUNC_SOCKET;
	}
	
	lsaServeraddr.sin_family=AF_INET;
	lsaServeraddr.sin_port=htons(piPort);
	lsaServeraddr.sin_addr.s_addr=INADDR_ANY;
	
	/*if want use this port,even if this prot is used*/
	int opt=1;
	setsockopt(*piServerfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
	
	//get root permission
	ChangePermission(1);
	
	if(-1==bind(*piServerfd,(struct sockaddr *)&lsaServeraddr,liSize))
	{
		sprintf(gstrLogBuf,"bind error : %s",strerror(errno));
 		WriteLog(LOG_ERROR,gstrLogBuf);
		return ERR_FUNC_BIND;
	}
	ChangePermission(0);
	
	if(-1==listen(*piServerfd,20))
	{
		sprintf(gstrLogBuf,"listen error : %s",strerror(errno));
 		WriteLog(LOG_ERROR,gstrLogBuf);
		return ERR_FUNC_LISTEN;
	}
	
	sprintf(gstrLogBuf,"tcp server (port:%d) start ok",piPort);
 	WriteLog(LOG_INFO,gstrLogBuf);
	
	return OK;
}


/*deal with connect*/
int DealWithClient(int piClientfd)
{
	char lsBuf[STRING_BUF_MAX_LEN];
	int liBufLen;
	int liErr=0;
	
	/*receive msg and deal with cmd*/
	while(1)
	{
		liBufLen=RecvMsg(piClientfd,lsBuf,sizeof(lsBuf));
		if(liBufLen<0)
		{
			liErr=ERR_FUNC_RECV;
			break;
		}
		
		if(0==liBufLen)
		{
			sleep(1);
			continue;
		}
	
		lsBuf[liBufLen]='\0';

		sprintf(gstrLogBuf,"recv:%s",lsBuf);
 		WriteLog(LOG_INFO,gstrLogBuf);
		
		/*cmd*/
		if(SESSION_OUT==DoRequest(piClientfd,lsBuf))
		{
			sprintf(gstrLogBuf,"client logout");
 			WriteLog(LOG_INFO,gstrLogBuf);
			break;
		}
		
	}
	close(piClientfd);

	return liErr;	
}

/*send message*/
int SendMsg(int piClientfd,char *psBuf,int piBufLen)
{
	int liOffset,lin,liLeft;
	liOffset=0;
	liLeft=piBufLen;
	
	/*pool send*/
	while(1)
	{
		lin=send(piClientfd,psBuf+liOffset,liLeft,0);
		if(lin<0)
		{
			if (errno == EINTR)
				continue;
			return lin;
		}
		/*continue to all send*/
		if(lin<liLeft)
		{
			liLeft-=lin;
			liOffset+=lin;
			continue;
		}
		return piBufLen;
	}
	return piBufLen;
}

/*receive message*/
int RecvMsg(int piClientfd, char psBuf[], int piLen)
{
	int lin;
	while(1)
	{
		lin=recv(piClientfd,psBuf,piLen,0);
		if(lin<0)
		{
			if (errno == EINTR)
				continue;
			return lin;
		}
		return lin;
	}
	return lin;
}

/*deal with command*/
int DoRequest(int piClientfd,char psBuf[])
{
	char *lpEnd=&psBuf[strlen(psBuf)-1];
	int liErr;
	int li;

	/*the last char must be \r or \n*/
	//if('\r'==*lpEnd||'\n'==*lpEnd)
	{
		/*search the command function*/
		for(li=0;gRtspCmdsWithFunc[li].pstrCmdName;li++)
		{
			if(0==memcmp(gRtspCmdsWithFunc[li].pstrCmdName,psBuf,strlen(gRtspCmdsWithFunc[li].pstrCmdName)))
			{
				return gRtspCmdsWithFunc[li].pCmdHandler(piClientfd,psBuf);
			}
		}

		sprintf(gstrLogBuf,"not find any function for this command");
 		WriteLog(LOG_INFO,gstrLogBuf);
		
		return liErr;
	}
	
	return liErr;
}



int DoOptions(int piClientfd,char *psBuf)
{
	CmdItem lCmdItem;
	char lstrSend[4096];

	memset(&lCmdItem,0,sizeof(CmdItem));

	//get all item info, from psBuf to lCmdItem struct
	DoAllLineRequest(psBuf,&lCmdItem);

	strcpy(gSessionGlobal.strCurrentUrl,lCmdItem.strUrl);
	gSessionGlobal.iCurrentSeq=lCmdItem.iSeq;

	//printf("seq:%d\n",lCmdItem.iSeq);
	
	//response the options to client
	sprintf(lstrSend,RESPONSE_OPTIONS,200,GetRtspStatusCodeDescription(200),gSessionGlobal.iCurrentSeq);
	SendMsg(piClientfd,lstrSend,strlen(lstrSend));

 	sprintf(gstrLogBuf,"send:\n%s",lstrSend);
 	WriteLog(LOG_INFO,gstrLogBuf);

	return 0;
}

int DoDescribe(int piClientfd,char *psBuf)
{
	CmdItem lCmdItem;
	char lstrSend[4096];
	
	memset(&lCmdItem,0,sizeof(CmdItem));
	
	//get all item info from psBuf to lCmdItem struct
	DoAllLineRequest(psBuf,&lCmdItem);
	
	strcpy(gSessionGlobal.strCurrentUrl,lCmdItem.strUrl);
	gSessionGlobal.iCurrentSeq=lCmdItem.iSeq;

	//response the describe to client
	sprintf(lstrSend,RESPONSE_DESCRIBE,200,GetRtspStatusCodeDescription(200),gSessionGlobal.iCurrentSeq,gSessionGlobal.strCurrentUrl);
	SendMsg(piClientfd,lstrSend,strlen(lstrSend));

 	sprintf(gstrLogBuf,"send:\n%s",lstrSend);
 	WriteLog(LOG_INFO,gstrLogBuf);	

	return 0;
}

int DoSetup(int piClientfd,char *psBuf)
{
	CmdItem lCmdItem;
	char lstrSend[4096];
	
	memset(&lCmdItem,0,sizeof(CmdItem));
	
	//get all item info from psBuf to lCmdItem struct
	DoAllLineRequest(psBuf,&lCmdItem);

/*	if(0!=strcmp(gSessionGlobal.strCurrentUrl,lCmdItem.strUrl))*/
/*	{*/
/*		sprintf(lstrSend,RESPONSE_SETUP_ERROR,100,GetRtspStatusCodeDescription(100),gSessionGlobal.iCurrentSeq);*/
/*		SendMsg(piClientfd,lstrSend,strlen(lstrSend));*/

/*		sprintf(gstrLogBuf,"send:\n%s",lstrSend);*/
/* 		WriteLog(LOG_INFO,gstrLogBuf);*/

/*		return ERR_SETUP_URL;*/
/*	}*/
	
	gSessionGlobal.iCurrentSeq=lCmdItem.iSeq;
	gSessionGlobal.iMarkTcp=lCmdItem.iMarkTcp;
	gSessionGlobal.iRtpPort=lCmdItem.iRtpPort;
	gSessionGlobal.iRtcpPort=lCmdItem.iRtcpPort;

	//create session
	srand((int)time(0));
	sprintf(gSessionGlobal.strCurrentSession,"%04d%04d",rand()%10000,rand()%10000);

	//response the describe to client
	sprintf(lstrSend,RESPONSE_SETUP,200,GetRtspStatusCodeDescription(200),gSessionGlobal.iCurrentSeq,lCmdItem.strTransport,gSessionGlobal.strCurrentSession);
	SendMsg(piClientfd,lstrSend,strlen(lstrSend));

 	sprintf(gstrLogBuf,"send:\n%s",lstrSend);
 	WriteLog(LOG_INFO,gstrLogBuf);

	printf("********^^^^^^^^^rtp port:%d^^^^^^^**********\n",lCmdItem.iRtpPort);

	//send infromation to rtp serverport
	QueueMsgbuf lQueueMsg;
	lQueueMsg.ltype=1;
	lQueueMsg.iCommand=0;
	lQueueMsg.iMarkTcp=gSessionGlobal.iMarkTcp;
	strcpy(lQueueMsg.strAddr,gSessionGlobal.strClientAddr);
	lQueueMsg.iPort=gSessionGlobal.iRtpPort;
	strcpy(lQueueMsg.strSession,gSessionGlobal.strCurrentSession);

	//find url positon
	pCameraInfo lpCameraTemp;
	lpCameraTemp=gpCameraHead;
	
	while(NULL!=lpCameraTemp)
	{
		printf("***************%s:%s**********\n",lpCameraTemp->strVisitUrl,gSessionGlobal.strCurrentUrl);
		if(0==lpCameraTemp->iType)
		{
			if(0==memcmp(lpCameraTemp->strVisitUrl,gSessionGlobal.strCurrentUrl,strlen(lpCameraTemp->strVisitUrl)))
				break;
		}
		else
		{
			if(0==strcmp(lpCameraTemp->strVisitUrl,gSessionGlobal.strCurrentUrl))
				break;
		}
		lpCameraTemp=lpCameraTemp->next;
	}
	
	//printf("11111111afadfasdffa1111111111111\n");

 	//printf("111111111111111111111111111::1111111\n");
 	if(0!=lpCameraTemp->iType)
 	{
 		//printf("1111111111111111111111111111111111\n");
		SendQueueMsg(lpCameraTemp->iMsqId,&lQueueMsg);
	}	
	else
	{
	//printf("11111111122221111111111111111111111111\n");
		char lstrPlaybackFile[256];
		int liPathPos;
		char lstrCmd[256];
		liPathPos=strlen(lpCameraTemp->strVisitUrl);
		strcpy(lstrPlaybackFile,lpCameraTemp->strRealUrl);
		strcat(lstrPlaybackFile,gSessionGlobal.strCurrentUrl+liPathPos);	
	 	
	 	sprintf(lstrCmd,"./playback %s %d %s",lQueueMsg.strAddr,lQueueMsg.iPort,lstrPlaybackFile);
	 	
	 	sprintf(gstrLogBuf,"exec:%s",lstrCmd);
	 	WriteLog(LOG_INFO,gstrLogBuf);
	 	
	 	int liPid=fork();
	 	if(0==liPid)
		{
			system(lstrCmd);
			exit(0);
		}
	}
/*	printf("***************************\n");*/
/*	printf("***************************\n");*/
	

	return 0;
}

int DoPlay(int piClientfd,char *psBuf)
{
	CmdItem lCmdItem;
	char lstrSend[4096];
	
	memset(&lCmdItem,0,sizeof(CmdItem));
	
	//get all item info from psBuf to lCmdItem struct
	DoAllLineRequest(psBuf,&lCmdItem);

	if(0!=strcmp(gSessionGlobal.strCurrentUrl,lCmdItem.strUrl))
	{
		sprintf(lstrSend,RESPONSE_PLAY_ERROR,100,GetRtspStatusCodeDescription(100),gSessionGlobal.iCurrentSeq);
		SendMsg(piClientfd,lstrSend,strlen(lstrSend));
		return ERR_PLAY_URL;
	}

	if(0!=strcmp(gSessionGlobal.strCurrentSession,lCmdItem.strSession))
	{
		sprintf(lstrSend,RESPONSE_PLAY_ERROR,400,GetRtspStatusCodeDescription(400),gSessionGlobal.iCurrentSeq);
		SendMsg(piClientfd,lstrSend,strlen(lstrSend));
		return ERR_PLAY_SESSION;
	}
	
	gSessionGlobal.iCurrentSeq=lCmdItem.iSeq;
	gSessionGlobal.iRangeStart=lCmdItem.iRangeStart;
	gSessionGlobal.iRangeEnd=lCmdItem.iRangeEnd;


	//send infromation to rtp serverport
	QueueMsgbuf lQueueMsg;
	lQueueMsg.ltype=1;
	lQueueMsg.iCommand=1;
	lQueueMsg.iMarkTcp=gSessionGlobal.iMarkTcp;
	strcpy(lQueueMsg.strAddr,gSessionGlobal.strClientAddr);
	lQueueMsg.iPort=gSessionGlobal.iRtpPort;
	strcpy(lQueueMsg.strSession,gSessionGlobal.strCurrentSession);

	//find url positon
	pCameraInfo lpCameraTemp;
	lpCameraTemp=gpCameraHead;
	
	while(NULL!=lpCameraTemp)
	{
		if(0==lpCameraTemp->iType)
		{
			if(0==memcmp(lpCameraTemp->strVisitUrl,gSessionGlobal.strCurrentUrl,strlen(lpCameraTemp->strVisitUrl)))
				break;
		}
		else
		{
			if(0==strcmp(lpCameraTemp->strVisitUrl,gSessionGlobal.strCurrentUrl))
				break;
		}
		lpCameraTemp=lpCameraTemp->next;
	}
	
	if(NULL==lpCameraTemp)
	{
		return -1;
	}

	if(0!=lpCameraTemp->iType)
	{
		sprintf(gstrLogBuf,"send to ipc :%d",lpCameraTemp->iMsqId);
	 	WriteLog(LOG_INFO,gstrLogBuf);

		SendQueueMsg(lpCameraTemp->iMsqId,&lQueueMsg);
	}
	else
	{
		
	}
	

	//wait for 5 second,for informtion to rtp programe
	sleep(2);

	//response the describe to client
	sprintf(lstrSend,RESPONSE_PLAY,200,GetRtspStatusCodeDescription(200),gSessionGlobal.iCurrentSeq,gSessionGlobal.strCurrentSession,gSessionGlobal.iRangeStart,gSessionGlobal.iRangeEnd);
	SendMsg(piClientfd,lstrSend,strlen(lstrSend));

 	sprintf(gstrLogBuf,"send:\n%s",lstrSend);
 	WriteLog(LOG_INFO,gstrLogBuf);
 	
 	

	return 0;
}

int DoPause(int piClientfd,char *psBuf)
{
	return 0;
}

int DoTearDown(int piClientfd,char *psBuf)
{
	close(piClientfd);
	return SESSION_OUT;
}

int DoOrder(int piClientfd,char *psBuf)
{
	//send infromation to rtp serverport
	QueueMsgbuf lQueueMsg;
	lQueueMsg.ltype=1;
	switch(psBuf[6])
	{
	case 'U':
		lQueueMsg.iCommand=11;
		break;
	case 'D':
		lQueueMsg.iCommand=12;
		break;
	case 'L':
		lQueueMsg.iCommand=13;
		break;
	case 'R':
		lQueueMsg.iCommand=14;
		break;
	default:
		sprintf(gstrLogBuf,"no %c order",psBuf[6]);
	 	WriteLog(LOG_INFO,gstrLogBuf);
		return 0;
	}

	//printf("********%c:%d************\n",psBuf[6],lQueueMsg.iCommand);

	//find url positon
	pCameraInfo lpCameraTemp;
	lpCameraTemp=gpCameraHead;
	
	while(NULL!=lpCameraTemp)
	{
		if(0==lpCameraTemp->iType)
		{
			continue;
		}
		else
		{
			if(0==strcmp(lpCameraTemp->strVisitUrl,gSessionGlobal.strCurrentUrl))
				break;
		}
		lpCameraTemp=lpCameraTemp->next;
	}
	
	if(NULL==lpCameraTemp)
	{
		return -1;
	}

	if(0!=lpCameraTemp->iType)
	{
		sprintf(gstrLogBuf,"send to ipc :%d order:%c",lpCameraTemp->iMsqId,psBuf[6]);
	 	WriteLog(LOG_INFO,gstrLogBuf);

		SendQueueMsg(lpCameraTemp->iMsqId,&lQueueMsg);
	}

	return 0;
}

int ChangePermission(BOOL pbMarkRoot)
{
	uid_t lruid,leuid,lsuid;
	
	if(gbRootPermissionNow==pbMarkRoot)
		return 0;

	gbRootPermissionNow=!gbRootPermissionNow;

	getresuid(&lruid, &leuid, &lsuid);
/*	printf("ruid:%d;euid:%d;suid:%d\n",lruid,leuid,lsuid);*/
	setreuid(leuid,lruid);
/*	getresuid(&lruid, &leuid, &lsuid);*/
/*	printf("end:ruid:%d;euid:%d;suid:%d\n",lruid,leuid,lsuid);*/

	return 0;
}

//get item value from config file
int GetConfigValue(char *ppstrFile,char *ppstrSection,char *ppstrItem,char *ppstrValue)
{
	FILE *lpFp;
	char lstrLine[1024+1];
	char lstrSection[50];
	char lstrItem[50];
	int li;
	char *lpstrPos;
	int liMarkOk=0;
	
	memset(lstrLine,0,sizeof(lstrLine));
	memset(lstrSection,0,sizeof(lstrSection));
	memset(lstrItem,0,sizeof(lstrItem));
	
	lpFp=fopen(ppstrFile,"r");
	if(NULL==lpFp) //如果失败了
	{
		sprintf(gstrLogBuf,"open %s file fault",ppstrFile);
		WriteLog(LOG_ERROR,gstrLogBuf);
		return ERR_OPEN_CONFIG_FILE;
	}


	while(1)
	{
		memset(lstrLine,0,sizeof(lstrLine));
	
		if(NULL==fgets(lstrLine,1024,lpFp))
			break;
	
		TrimWrap(lstrLine);
		TrimSpace(lstrLine);
		
		lpstrPos=strchr(lstrLine,'#');
		if(NULL!=lpstrPos)
			*lpstrPos=0;
		
		//deal with section
		if(0==liMarkOk)
		{
			sprintf(lstrSection,"[%s]",ppstrSection);
			if(0==strcmp(lstrSection,lstrLine))
			{
				liMarkOk=1;
			}
			continue;
		}

		//deal with item
		lpstrPos=strchr(lstrLine,'=');
		if(NULL==lpstrPos)
			continue;
			
		//get item name
		*lpstrPos=0;
		strcpy(lstrItem,lstrLine);
		TrimSpace(lstrItem);

		if(0!=strcmp(lstrItem,ppstrItem))
		{
			continue;
		}
		*lpstrPos='=';
		strcpy(ppstrValue,lpstrPos+1);
		TrimSpace(ppstrValue);
		liMarkOk=2;
		break;
	}
	
	fclose(lpFp);
	
	if(0==liMarkOk)
		return ERR_CONFIG_NO_THIS_SECTION;
	else if(1==liMarkOk)
		return ERR_CONFIG_NO_THIS_ITEM;
	
	return 0;
}
	
//remove \r \n at the top and bottom
int TrimWrap(char *lstrStr)
{
	int li=0;
	
	while('\r'==lstrStr[li]||'\n'==lstrStr[li])
	{
		li++;
	}
	
	strcpy(lstrStr,lstrStr+li);
	
	li=strlen(lstrStr)-1;
	
	while('\r'==lstrStr[li]||'\n'==lstrStr[li])
	{
		li--;
	}
	lstrStr[li+1]=0;
	
	return 0;
}

//remove space at the top and bottom
int TrimSpace(char *lstrStr)
{
	int li=0;
	
	while(' '==lstrStr[li])
	{
		li++;
	}
	
	strcpy(lstrStr,lstrStr+li);
	
	li=strlen(lstrStr)-1;
	
	while(' '==lstrStr[li])
	{
		li--;
	}
	lstrStr[li+1]=0;
	
	return 0;
}

int GetAllConfigInfo()
{
	char lstrConfigPath[FILE_MAX_LEN];
	char lstrValue[256];
	char lstrCamera[10+1];
	int li;
	CameraInfo *lpCamera;
	int liRet=0;
	pCameraInfo lpCameraPos;
	
	memset(lstrValue,0,sizeof(lstrValue));
	memset(lstrCamera,0,sizeof(lstrCamera));
	
	strcpy(lstrConfigPath,"rtspserver.config");
	
	//get internet informtion
	liRet=GetConfigValue(lstrConfigPath,"internet","serverport",lstrValue);
	if(0!=liRet)
	{
		sprintf(gstrLogBuf,"serverport is not in %s config file",lstrConfigPath);
 		WriteLog(LOG_ERROR,gstrLogBuf);
 		return liRet;
	}
	giServerPort=atoi(lstrValue);
	//printf("%d\n",giServerPort);
	
	//get camera informtion
	DeleteCameraInfo(gpCameraHead);
	for(li=1;;li++)
	{
		lpCamera=malloc(sizeof(CameraInfo));
	
		sprintf(lstrCamera,"camera%d",li);
		liRet=GetConfigValue(lstrConfigPath,lstrCamera,"type",lstrValue);
		if(0!=liRet)
		{
			sprintf(gstrLogBuf,"type(first item) is not in %s config file",lstrConfigPath);
	 		WriteLog(LOG_WARNING,gstrLogBuf);
	 		liRet=0;
	 		break;
		}
		lpCamera->iType=atoi(lstrValue);
		//printf("%d\n",lpCamera->iType);
		
		liRet=GetConfigValue(lstrConfigPath,lstrCamera,"realurl",lstrValue);
		if(0!=liRet)
		{
			sprintf(gstrLogBuf,"realurl is not in %s config file",lstrConfigPath);
	 		WriteLog(LOG_WARNING,gstrLogBuf);
	 		break;
		}
		strcpy(lpCamera->strRealUrl,lstrValue);
		//printf("%s\n",lstrValue);
		
		liRet=GetConfigValue(lstrConfigPath,lstrCamera,"visiturl",lstrValue);
		if(0!=liRet)
		{
			sprintf(gstrLogBuf,"visiturl is not in %s config file",lstrConfigPath);
	 		WriteLog(LOG_WARNING,gstrLogBuf);
	 		break;
		}
		strcpy(lpCamera->strVisitUrl,lstrValue);
		//printf("%s\n",lstrValue);
		
		liRet=GetConfigValue(lstrConfigPath,lstrCamera,"msgid",lstrValue);
		if(0!=liRet)
		{
			sprintf(gstrLogBuf,"msgid is not in %s config file",lstrConfigPath);
	 		WriteLog(LOG_WARNING,gstrLogBuf);
	 		break;
		}
		lpCamera->iMsqId=strtol(lstrValue,NULL,16);
		//printf("%d\n",lpCamera->iMsqId);
		
		liRet=GetConfigValue(lstrConfigPath,lstrCamera,"videopath",lstrValue);
		if(0!=liRet)
		{
			sprintf(gstrLogBuf,"videopath is not in %s config file",lstrConfigPath);
	 		WriteLog(LOG_WARNING,gstrLogBuf);
	 		break;
		}
		strcpy(lpCamera->strVideoPath,lstrValue);
		lpCamera->next=NULL;
		//printf("%s\n",lstrValue);
		
		if(1==li)
		{
			gpCameraHead=lpCamera;
			lpCameraPos=lpCamera;
		}
		else
		{
			lpCameraPos->next=lpCamera;
			lpCameraPos=lpCamera;
		}
		
	}
	
	return liRet;
}

int DeleteCameraInfo(pCameraInfo ppCameraPos)
{
	if(NULL==ppCameraPos)
		return 0;
	
	pCameraInfo lpCameraTemp;

	lpCameraTemp=ppCameraPos;
	ppCameraPos=ppCameraPos->next;
	free(lpCameraTemp);
	
	while(NULL!=ppCameraPos)
	{
		lpCameraTemp=ppCameraPos;
		ppCameraPos=ppCameraPos->next;
		free(lpCameraTemp);
	}
	
	return 0;
}

int OpenMsgQueue(int piKey)
{
	int liQueueId;
	liQueueId=msgget(piKey,IPC_CREAT|0666);
	if(liQueueId<0)
		return ERR_OPEN_MSG_QUEUE;
	
	return liQueueId;	
}

int CloseMsgQueue(int piQueueId)
{
	if( msgctl( piQueueId, IPC_RMID, 0) < -1)
	{
		return ERR_CLOSE_MSG_QUEUE;
	}

	return 0;
}

int SendQueueMsg(int piQueueId,QueueMsgbuf *ppQueueMsgBuf)
{
	if(0>msgsnd(piQueueId, ppQueueMsgBuf, sizeof(QueueMsgbuf)-sizeof(long),IPC_NOWAIT))
		return ERR_SEND_MSG_TO_QUEUE;
	
	return 0;
}

int RecvQueueMsg(int piQueueId,QueueMsgbuf *ppQueueMsgBuf)
{
	if(0>msgrcv(piQueueId, ppQueueMsgBuf, sizeof(QueueMsgbuf)-sizeof(long),0,IPC_NOWAIT))
		return ERR_RECV_MSG_FROM_QUEUE;
	
	return 0;
}

int StartAllMsgQueue()
{
	CameraInfo *lpCamera;
	int liQueueId;

	lpCamera=gpCameraHead;
	while(lpCamera)
	{
		liQueueId=OpenMsgQueue(lpCamera->iMsqId);
		if(liQueueId<0)
		{
			sprintf(gstrLogBuf,"open message queue error. id:%x ",lpCamera->iMsqId);
 			WriteLog(LOG_ERROR,gstrLogBuf);
			return liQueueId;
		}
		lpCamera->iMsqId=liQueueId;
		lpCamera=lpCamera->next;
	}
	
	return 0;
}

int PrintAllCameraInfo()
{
	CameraInfo *lpCamera;

	lpCamera=gpCameraHead;
	while(lpCamera)
	{
		PrintOneCameraInfo(lpCamera);
		lpCamera=lpCamera->next;
	}
	
	return 0;
}


int PrintOneCameraInfo(CameraInfo *pCameraInfo)
{
	sprintf(gstrLogBuf,"***********One Camera Info Start********* ");
 	WriteLog(LOG_INFO,gstrLogBuf);

	sprintf(gstrLogBuf,"iType:%d",pCameraInfo->iType);
 	WriteLog(LOG_INFO,gstrLogBuf);

	sprintf(gstrLogBuf,"strRealUrl:%s",pCameraInfo->strRealUrl);
 	WriteLog(LOG_INFO,gstrLogBuf);
 	
 	sprintf(gstrLogBuf,"strVisitUrl:%s",pCameraInfo->strVisitUrl);
 	WriteLog(LOG_INFO,gstrLogBuf);
 	
 	sprintf(gstrLogBuf,"iMsqId:0x%x",pCameraInfo->iMsqId);
 	WriteLog(LOG_INFO,gstrLogBuf);
 	
 	sprintf(gstrLogBuf,"strVideoPath:%s",pCameraInfo->strVideoPath);
 	WriteLog(LOG_INFO,gstrLogBuf);
 	
 	sprintf(gstrLogBuf,"***********One Camera Info End********* ");
 	WriteLog(LOG_INFO,gstrLogBuf);
 	
 	return 0;
}

int StartAllRtpServer()
{
	CameraInfo *lpCamera;

	lpCamera=gpCameraHead;
	while(lpCamera)
	{
		if(0!=lpCamera->iType)
		{
			StartOneRtpServer(lpCamera);
		}
		
		lpCamera=lpCamera->next;
	}
	
	return 0;
}

int StartOneRtpServer(CameraInfo *pCameraInfo)
{
	int liPid;
	char lstrStartArgv[256];
	
	/*create child*/
	liPid=fork();
	if(0==liPid)
	{
		sprintf(gstrLogBuf,"start rtp server \"%s %s %s %d\"",RTP_SERVER_NAME,pCameraInfo->strRealUrl,pCameraInfo->strVideoPath,pCameraInfo->iMsqId);
 		WriteLog(LOG_INFO,gstrLogBuf);
 		
 		sprintf(lstrStartArgv,"%s %s %s %d",RTP_SERVER_NAME,pCameraInfo->strRealUrl,pCameraInfo->strVideoPath,pCameraInfo->iMsqId);
 		
 		system(lstrStartArgv);
 		
/*		execlp(RTP_SERVER_NAME,RTP_SERVER_NAME,pCameraInfo->strRealUrl,pCameraInfo->strVideoPath,pCameraInfo->iMsqId,NULL);*/
		exit(0);
	}
	else if(liPid>0)
	{
		;
	}
	else
	{
		/*fork error*/
		;
	}
	
	return 0;
}


int SendRtpIpPortInfo(char *pstrIp,int piPort)
{
	
}











